/*************************************************
* Title：
* Author：Opportunity 
* Discribe：双向链表
* CreateTime：2020-04-04 17:08:43
* Version：1.0
* Modify Recoder：
*************************************************/

using TinyToolKit;

namespace TinyToolKit
{
    public class DoubleLinkedList<T> where T : class, new()
    {
        public DoubleLinkedListNode<T> Head = null; //表头
        public DoubleLinkedListNode<T> Tail = null; //表尾 

        protected int _Count = 0; //节点数量
        public int Count => _Count;

        public DoubleLinkedListNode<T> AddFirst(T t)
        {
            DoubleLinkedListNode<T> pList = TReferencePool.Acquire<DoubleLinkedListNode<T>>();
            pList.pre = null;
            pList.next = null;
            pList.t = t;
            return AddFirst(pList);
        }

        public DoubleLinkedListNode<T> AddFirst(DoubleLinkedListNode<T> pNode)
        {
            if (pNode == null) return null;

            pNode.pre = null;
            if (Head == null)
            {
                Head = Tail = pNode;
            }
            else
            {
                pNode.next = Head;
                Head.pre = pNode;
                Head = pNode;
            }

            _Count++;
            return Head;
        }

        public DoubleLinkedListNode<T> AddLast(T t)
        {
            DoubleLinkedListNode<T> pList = TReferencePool.Acquire<DoubleLinkedListNode<T>>();
            pList.pre = null;
            pList.next = null;
            pList.t = t;
            return AddLast(pList);
        }

        public DoubleLinkedListNode<T> AddLast(DoubleLinkedListNode<T> pNode)
        {
            if (pNode == null) return null;

            pNode.next = null;
            if (Tail == null)
            {
                Head = Tail = null;
            }
            else
            {
                pNode.pre = Tail;
                Tail.next = pNode;
                Tail = pNode;
            }

            _Count++;
            return Tail;
        }

        public void Remove(DoubleLinkedListNode<T> pNode)
        {
            if (pNode == null) return;

            if (pNode == Head)
                Head = pNode.next;

            if (pNode == Tail)
                Tail = pNode.pre;

            if (pNode.pre != null)
                pNode.pre.next = pNode.next;

            if (pNode.next != null)
                pNode.next.pre = pNode.pre;

            TReferencePool.Release(pNode);
            _Count--;
        }

        public void MoveToFirst(DoubleLinkedListNode<T> pNode)
        {
            if (pNode == null || pNode == Head) return;
            if (pNode.pre == null && pNode.next == null) return;

            if (pNode == Tail)
                Tail = pNode.pre;

            if (pNode.pre != null)
                pNode.pre.next = pNode.next;

            if (pNode.next != null)
                pNode.next.pre = pNode.pre;

            pNode.pre = null;
            pNode.next = Head;
            Head.pre = pNode;
            Head = pNode;

            if (Tail == null)
                Tail = Head;
        }
    }

    /// <summary>
    /// 双向链表的结点
    /// </summary>
    /// <typeparam name="T">结点存储的类型</typeparam>
    public class DoubleLinkedListNode<T> : IReference where T : class, new()
    {
        public DoubleLinkedListNode<T> pre = null; //前一个节点
        public DoubleLinkedListNode<T> next = null; //后一个节点
        public T t = null; //当前节点上数据

        public void Clear()
        {
            pre = null;
            next = null;
            t = null;
        }
    }
}